package org.atlantis.nio;

import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;

public class ChannelCopier {

	public static void main(String[] args) throws Exception {
		// 只读通道（因为是InputStream的通道，所以只能读取），即使有write方法，但是一旦调用就会抛出异常
		ReadableByteChannel source = Channels.newChannel(System.in);
		// 只写通道（因为是OutputStream的通道，所以只能写入），即使有read方法，但是一旦调用就会抛出异常
		WritableByteChannel dest = Channels.newChannel(System.out);
		copyB(source, dest);
		source.close();
		dest.close();
	}

	/**
	 * 第一种拷贝方式。
	 */
	static void copyA(ReadableByteChannel source, WritableByteChannel dest) throws Exception {
		ByteBuffer buf = ByteBuffer.allocateDirect(8 * 1024);
		while (source.read(buf) != -1) {
			buf.flip();
			dest.write(buf);
			// 如果还有剩余数据则compact压缩，如果没有剩余数据compact则相当于clear方法
			buf.compact();
		}

		// 输入结束，则检查一下是否还有剩余的数据没有输出
		buf.flip();
		while (buf.hasRemaining()) {
			dest.write(buf);
		}
	}

	/**
	 * 第二种拷贝方式。
	 */
	static void copyB(ReadableByteChannel source, WritableByteChannel dest) throws Exception {
		ByteBuffer buf = ByteBuffer.allocateDirect(8 * 1024);
		while (source.read(buf) != -1) {
			buf.flip();
			while (buf.hasRemaining())
				dest.write(buf);
			buf.clear();
		}
	}
}
